package com.boesch.electroOffice.business.businessObjectImpl;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.joda.time.LocalDate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.boesch.electroOffice.business.businessObject.WorkingHoursBusinessObject;
import com.boesch.electroOffice.business.common.BusinessException;
import com.boesch.electroOffice.business.common.BusinessExceptionMessages;
import com.boesch.electroOffice.dataaccess.common.IllegalDataAccessException;
import com.boesch.electroOffice.dataaccess.dao.IdentifierDao;
import com.boesch.electroOffice.dataaccess.dao.WorkingHourDao;
import com.boesch.electroOffice.model.electroOffice.Identifier;
import com.boesch.electroOffice.model.electroOffice.WorkingHour;
import com.boesch.electroOffice.model.wrapper.WorkingHoursEntry;
import com.boesch.electroOffice.utils.DateUtils;
import com.boesch.electroOffice.utils.UserUtils;
import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.model.User;
import com.liferay.portal.service.UserLocalServiceUtil;

@Service
public class WorkingHoursBusinessObjectImpl implements WorkingHoursBusinessObject {

	@Autowired
	private WorkingHourDao workingHourDao;
	@Autowired
	private IdentifierDao identifierDao;

	public List<WorkingHoursEntry> getWorkingHourEntriesByAppointmentIdAndCalendarWeek(long appointmentId, int year, int week) throws IllegalDataAccessException,
			BusinessException {
		Timestamp startDate = DateUtils.getDateOfMondayByYearAndWeek(year, week);
		Timestamp endDate = DateUtils.getDatePlusDays(startDate, 6);
		List<WorkingHour> workingHours = workingHourDao.readWorkingHoursByAppointmentIdStartDateAndEndDate(appointmentId, startDate, endDate);
		List<WorkingHoursEntry> workingHoursEntries = mapWorkingHoursToWorkingHourEntries(workingHours, DateUtils.convertTimestampToLocalDate(startDate));
		return workingHoursEntries;
	}

	public void saveWorkingHoursEntry(WorkingHoursEntry entry, User currentUser) throws IllegalDataAccessException, BusinessException {
		workingHourDao.saveWorkingHoursEntry(entry, currentUser);
	}

	public void deleteWorkingHoursEntry(WorkingHoursEntry entry, User currentUser) throws IllegalDataAccessException, BusinessException {
		workingHourDao.deleteWorkingHoursEntry(entry, currentUser);
	}

	private List<WorkingHoursEntry> mapWorkingHoursToWorkingHourEntries(List<WorkingHour> workingHours, LocalDate startDate) throws IllegalDataAccessException,
			BusinessException {
		Map<String, WorkingHoursEntry> workingHourEntries = new HashMap<String, WorkingHoursEntry>();
		List<WorkingHoursEntry> entries = new ArrayList<WorkingHoursEntry>();
		try {
			Identifier workingIdentifier = null;
			User user = null;

			if (null == workingIdentifier) {
				workingIdentifier = identifierDao.getIdentifierByEntityAndIdentifier("WORKING-IDENTIFIER", "APPOINTMENT");
			}

			for (WorkingHour workingHour : workingHours) {
				Integer appointmentId = workingHour.getAppointmentId();

				if (null == user || user.getUserId() != workingHour.getLrUserId()) {
					user = UserLocalServiceUtil.getUserById(workingHour.getLrUserId());
				}

				String key = workingIdentifier.getName() + appointmentId + user.getUserId();
				WorkingHoursEntry workingHourEntry = workingHourEntries.get(key);

				if (null == workingHourEntry) {
					workingHourEntry = new WorkingHoursEntry();
				}
				workingHourEntry.setUser(user);
				setWorkingHour(workingHour, workingHourEntry);
				workingHourEntries.put(key, workingHourEntry);
			}
			entries = new ArrayList<WorkingHoursEntry>(workingHourEntries.values());
			addDefaultWeekReportEntry(entries, workingIdentifier, startDate);
		} catch (PortalException e) {
			throw new BusinessException(BusinessExceptionMessages.USER_NOT_FOUND.getValue(), e);
		} catch (SystemException e) {
			throw new BusinessException(BusinessExceptionMessages.USER_NOT_FOUND.getValue(), e);
		}
		return entries;
	}

	private void setWorkingHour(WorkingHour workingHour, WorkingHoursEntry workingHoursEntry) {
		Integer dayOfWeek = workingHour.getWorkdate().getDayOfWeek();
		switch (dayOfWeek) {
		case 1:
			workingHoursEntry.setMonday(workingHour);
			break;
		case 2:
			workingHoursEntry.setTuesday(workingHour);
			break;
		case 3:
			workingHoursEntry.setWednesday(workingHour);
			break;
		case 4:
			workingHoursEntry.setThursday(workingHour);
			break;
		case 5:
			workingHoursEntry.setFriday(workingHour);
			break;
		case 6:
			workingHoursEntry.setSaturday(workingHour);
			break;
		case 7:
			workingHoursEntry.setSunday(workingHour);
			break;
		}
	}

	private void addDefaultWeekReportEntry(List<WorkingHoursEntry> entries, Identifier workingIdentifier, LocalDate startDate) {
		User currentUser = UserUtils.getCurrentUser();
		WorkingHoursEntry entry = new WorkingHoursEntry();
		entry.setWorkingIdentifier(workingIdentifier);

		entry.setMonday(createWorkingHour(workingIdentifier, startDate, 0, currentUser));
		entry.setTuesday(createWorkingHour(workingIdentifier, startDate, 1, currentUser));
		entry.setWednesday(createWorkingHour(workingIdentifier, startDate, 2, currentUser));
		entry.setThursday(createWorkingHour(workingIdentifier, startDate, 3, currentUser));
		entry.setFriday(createWorkingHour(workingIdentifier, startDate, 4, currentUser));
		entry.setSaturday(createWorkingHour(workingIdentifier, startDate, 5, currentUser));
		entry.setSunday(createWorkingHour(workingIdentifier, startDate, 6, currentUser));
		entry.setIsDefault(true);
		entries.add(entry);
	}

	private WorkingHour createWorkingHour(Identifier workingIdentifier, LocalDate startDate, int plusDays, User currentUser) {
		WorkingHour workingHour = new WorkingHour();
		workingHour.setWorkingIdentifier(workingIdentifier);
		workingHour.setLrUserId(0L);
		workingHour.setWorkdate(DateUtils.getDatePlusDays(startDate, plusDays));
		workingHour.setHours(0.0);
		return workingHour;
	}
}
